package service4gateway

import (
	Article "MyBlogv2/Servers/Article/article"
	"MyBlogv2/Servers/Article/articleservice"
	"MyBlogv2/blog-common/HttpCode"
	"MyBlogv2/blog-common/helper"
	"MyBlogv2/blog-common/models"
	"MyBlogv2/blog-common/oss"
	"MyBlogv2/blog-common/response"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/copier"
	"github.com/zeromicro/go-zero/core/discov"
	"github.com/zeromicro/go-zero/zrpc"
	"io"
	"path"
	"strconv"
)

var clientOfArticle Article.ArticleServiceClient

func init() {
	conn := zrpc.MustNewClient(zrpc.RpcClientConf{
		Etcd: discov.EtcdConf{
			Hosts: []string{"127.0.0.1:2379"},
			Key:   "Article.rpc",
		},
	})
	clientOfArticle = articleservice.NewArticleService(conn)

}
func GetRecommendList(c *gin.Context) {
	rsp, err := clientOfArticle.GetRecommendList(c, &Article.ArticleRequest{})
	if err != nil {
		response.ResponseError(c, HttpCode.FAILURE)
		return
	}
	var articleVoList []models.RecommendArticleVo
	copier.Copy(&articleVoList, rsp.GetRecommendArticleVoList())
	for i, v := range rsp.GetRecommendArticleVoList() {
		articleVoList[i].CreateTime = helper.TimestampToMyTime(v.CreateTime)
	}
	response.ResponseOK(c, articleVoList)
}

func GetArticlePageList(c *gin.Context) {
	pageNum, _ := strconv.Atoi(c.DefaultQuery("pageNum", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))
	rsp, _ := clientOfArticle.GetArticlePageList(c, &Article.ArticleRequest{PageNum: int64(pageNum), PageSize: int64(pageSize)})
	var articleVoList []models.ArticleVo
	copier.Copy(&articleVoList, rsp.Data)
	for i, v := range rsp.Data {
		articleVoList[i].CreateTime = helper.TimestampToMyTime(v.CreateTime)
		articleVoList[i].UpdateTime = helper.TimestampToMyTime(v.UpdateTime)
	}
	response.ResponseOK(c, gin.H{
		"total": rsp.Total,
		"page":  articleVoList,
	})
	return

}

func GetArticleDetailById(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))
	rsp, err := clientOfArticle.GetArticleDetailById(c, &Article.ArticleRequest{Id: int64(id)})
	if err != nil {
		response.ResponseError(c, HttpCode.FAILURE)
		return
	}
	var articleDetailVo models.ArticleDetailVo
	copier.Copy(&articleDetailVo, rsp)
	articleDetailVo.CreateTime = helper.TimestampToMyTime(rsp.CreateTime)
	articleDetailVo.UpdateTime = helper.TimestampToMyTime(rsp.UpdateTime)
	//TODO tag
	response.ResponseOK(c, articleDetailVo)
	return
}

func UpdateVisitCount(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))
	_, err := clientOfArticle.UpdateVisitCount(c, &Article.ArticleRequest{Id: int64(id)})
	if err != nil {
		response.ResponseError(c, HttpCode.FAILURE)
		return
	}
	response.ResponseOK(c, nil)
	return
}

func Related(c *gin.Context) {
	categoryId, _ := strconv.Atoi(c.Param("categoryId"))
	articleId, _ := strconv.Atoi(c.Param("articleId"))
	rsp, err := clientOfArticle.Related(c, &Article.ArticleRequest{CategoryId: int64(categoryId), ArticleId: int64(articleId)})
	if err != nil {
		response.ResponseError(c, HttpCode.FAILURE)
		return
	}
	var relatedArticleVoList []models.RelatedArticleVo
	copier.Copy(&relatedArticleVoList, &rsp.RelatedArticleVoList)
	for i, v := range rsp.RelatedArticleVoList {
		relatedArticleVoList[i].CreateTime = helper.TimestampToMyTime(v.CreateTime)
	}
	response.ResponseOK(c, relatedArticleVoList)
	return
}

func GetRandomArticleList(c *gin.Context) {
	rsp, err := clientOfArticle.GetRandomArticleList(c, &Article.ArticleRequest{})
	if err != nil {
		response.ResponseError(c, HttpCode.FAILURE)
		return
	}
	var articleVoList []models.ArticleVo
	copier.Copy(&articleVoList, rsp.GetArticleVoList())
	for i, v := range rsp.GetArticleVoList() {
		articleVoList[i].CreateTime = helper.TimestampToMyTime(v.CreateTime)
		articleVoList[i].UpdateTime = helper.TimestampToMyTime(v.UpdateTime)
	}
	response.ResponseOK(c, articleVoList)
	return
}

func InitSearchByTitle(c *gin.Context) {
	rsp, err := clientOfArticle.InitSearchByTitle(c, &Article.ArticleRequest{})
	if err != nil {
		response.ResponseError(c, HttpCode.FAILURE)
		return
	}
	response.ResponseOK(c, rsp.GetInitSearchTitleVoList())
	return
}
func GetHotArticleList(c *gin.Context) {
	var hotArticleVoList []models.HotArticleVo
	rsp, _ := clientOfArticle.GetHotArticleList(c, &Article.ArticleRequest{})
	copier.Copy(&hotArticleVoList, rsp.Data)
	response.ResponseOK(c, hotArticleVoList)
	return
}
func SearchArticleByContent(c *gin.Context) {
	keyword := c.Query("content")
	rsp, err := clientOfArticle.SearchArticleByContent(c, &Article.ArticleRequest{Keyword: keyword})
	if err != nil {
		response.ResponseError(c, HttpCode.FAILURE)
		return
	}
	if len(rsp.GetSearchArticleByContentVoList()) != 0 {
		response.ResponseOK(c, rsp.GetSearchArticleByContentVoList())
	} else {
		response.ResponseOK(c, new([]models.SearchArticleByContentVo))
	}
	return
}

func GetTimeLineList(c *gin.Context) {
	rsp, err := clientOfArticle.GetTimeLineList(c, &Article.ArticleRequest{})
	if err != nil {
		response.ResponseError(c, HttpCode.FAILURE)
		return
	}
	var timeLineVoList []models.TimeLineVo
	copier.Copy(&timeLineVoList, rsp.GetTimeLineVoList())
	for i, v := range rsp.GetTimeLineVoList() {
		timeLineVoList[i].CreateTime = helper.TimestampToMyTime(v.CreateTime)
	}
	response.ResponseOK(c, timeLineVoList)
	return
}

func UploadArticleCover(c *gin.Context) {
	file, _ := c.FormFile("articleCover")
	filename := file.Filename
	ext := path.Ext(filename)
	objectName := helper.GetUUID() + ext
	filePath, err := file.Open()
	if err != nil {
		response.ResponseError(c, HttpCode.FILE_UPLOAD_ERROR)
		return
	}
	articleCover, err := io.ReadAll(filePath)
	if err != nil {
		response.ResponseError(c, HttpCode.FILE_UPLOAD_ERROR)
		return
	}
	rsp, _ := clientOfArticle.UploadArticleCover(c, &Article.UploadArticleCoverRequest{
		ArticleCover: articleCover,
		Filename:     objectName,
	})
	if rsp.GetCode() == 200 {
		response.ResponseOK(c, rsp.Data)
	} else {
		response.ResponseError(c, HttpCode.FILE_UPLOAD_ERROR)
	}

}

func PublishArticle(c *gin.Context) {
	var articleDto Article.ArticleDto
	if err := c.ShouldBindJSON(&articleDto); err != nil {
		response.ResponseError(c, HttpCode.PARAM_ERROR)
		return
	}
	userId, _ := c.Get("userId")
	rsp, _ := clientOfArticle.PublishArticle(c, &Article.PublishArticleRequest{
		ArticleDto: &articleDto,
		UserId:     int64(userId.(int)),
	})
	if rsp.Code == 200 {
		response.ResponseOK(c, rsp.Data)
	} else {
		response.ResponseError(c, HttpCode.FAILURE)
	}

}

func UploadArticleImage(c *gin.Context) {
	file, _ := c.FormFile("articleImage")
	filename := file.Filename
	ext := path.Ext(filename)
	objectName := helper.GetUUID() + ext
	filePath, err := file.Open()
	if err != nil {
		response.ResponseError(c, HttpCode.FILE_UPLOAD_ERROR)
		return
	}
	uploadFilePath, err := oss.UploadFile(objectName, filePath)
	if err != nil {
		response.ResponseError(c, HttpCode.FILE_UPLOAD_ERROR)
		return
	}
	response.ResponseOK(c, uploadFilePath)
	return

}

func GetArticleList(c *gin.Context) {
	var articleVoList []models.ArticleListVo
	rsp, _ := clientOfArticle.GetArticleList(c, &Article.ArticleRequest{})
	copier.Copy(&articleVoList, rsp.Data)
	for i, v := range rsp.Data {
		articleVoList[i].CreateTime = helper.TimestampToMyTime(v.CreateTime)
	}
	response.ResponseOK(c, articleVoList)
	return
}

func SearchArticle(c *gin.Context) {

	var searchArticleDto models.SearchArticleDto
	if err := c.ShouldBindJSON(&searchArticleDto); err != nil {
		response.ResponseError(c, HttpCode.PARAM_ERROR)
		return
	}
	var articleVoList []models.ArticleListVo
	var searchArticleRequest Article.SearchArticleRequest
	searchArticleRequest.ArticleTitle = searchArticleDto.ArticleTitle
	searchArticleRequest.CategoryId = int64(searchArticleDto.CategoryId)
	if searchArticleDto.Status.Valid {
		searchArticleRequest.Status = searchArticleDto.Status.Int64
	}
	if searchArticleDto.IsTop.Valid {
		searchArticleRequest.IsTop = searchArticleDto.IsTop.Int64
	}
	rsp, _ := clientOfArticle.SearchArticle(c, &searchArticleRequest)
	copier.Copy(&articleVoList, rsp.Data)
	for i, v := range rsp.Data {
		articleVoList[i].CreateTime = helper.TimestampToMyTime(v.CreateTime)
	}
	response.ResponseOK(c, articleVoList)
	return

}

func UpdateArticleStatus(c *gin.Context) {
	id, _ := strconv.Atoi(c.Query("id"))
	status, _ := strconv.Atoi(c.Query("status"))
	rsp, _ := clientOfArticle.UpdateArticleStatus(c, &Article.UpdateArticleStatusRequest{
		Id:     int64(id),
		Status: int64(status),
	})
	if rsp.Code == 200 {
		response.ResponseOK(c, nil)
	} else {
		response.ResponseError(c, HttpCode.FAILURE)
	}
}

func UpdateArticleIsTop(c *gin.Context) {
	id, _ := strconv.Atoi(c.Query("id"))
	isTop, _ := strconv.Atoi(c.Query("isTop"))
	rsp, _ := clientOfArticle.UpdateArticleIsTop(c, &Article.UpdateArticleIsTopRequest{
		Id:    int64(id),
		IsTop: int64(isTop),
	})
	if rsp.Code == 200 {
		response.ResponseOK(c, nil)
	} else {
		response.ResponseError(c, HttpCode.FAILURE)
	}
}

func GetArticleEcho(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))
	var articleDto models.ArticleDto
	rsp, _ := clientOfArticle.GetArticleEcho(c, &Article.ArticleRequest{Id: int64(id)})
	copier.Copy(&articleDto, rsp.Data)
	response.ResponseOK(c, articleDto)
	return
}

func DeleteArticle(c *gin.Context) {
	var ids []int64
	if err := c.ShouldBindJSON(&ids); err != nil {
		response.ResponseError(c, HttpCode.PARAM_ERROR)
		return
	}
	rsp, _ := clientOfArticle.DeleteArticle(c, &Article.DeleteArticleRequest{Ids: ids})
	if rsp.Code == 200 {
		response.ResponseOK(c, nil)
	} else {
		response.ResponseError(c, HttpCode.FAILURE)
	}

}

func DeleteArticleCover(c *gin.Context) {
	response.ResponseOK(c, nil)
	return
}
